package com.googlecode.groovycpp.transform

import org.codehaus.groovy.ast.ASTNode
import org.codehaus.groovy.ast.AnnotationNode
import org.codehaus.groovy.ast.ClassNode
import org.codehaus.groovy.ast.MethodNode
import org.codehaus.groovy.ast.ModuleNode
import org.codehaus.groovy.ast.builder.AstBuilder
import org.codehaus.groovy.control.CompilePhase
import org.codehaus.groovy.control.SourceUnit
import org.codehaus.groovy.control.messages.SyntaxErrorMessage
import org.codehaus.groovy.syntax.SyntaxException
import org.codehaus.groovy.transform.ASTTransformation

import com.googlecode.groovycpp.StaticConstructorNode


class BaseTransformation implements ASTTransformation {
	protected final boolean logProgress;
	private final boolean useSynchronization;

	public BaseTransformation(boolean logProgress = true, boolean useSynchronization = true) {
		this.logProgress = logProgress;
		this.useSynchronization = useSynchronization;
	}

	protected void localTransform(AnnotationNode annotations, ClassNode clazz, SourceUnit source) { }
	protected void globalTransform(ModuleNode module, SourceUnit source) { }

	private final void transform(ASTNode[] astNodes, SourceUnit source) {
		if (logProgress) {
			println """\
Configuration Audit [${source.phaseDescription}]
\tNodes: ${astNodes}
\tOutput: ${source.configuration.output}
\tTargetByteCode: ${source.configuration.targetBytecode}
\tTargetDirectory: ${source.configuration.targetDirectory}
\tAST: ${source.ast.methods}"""
		}

		if (astNodes.length == 2 && astNodes[0] instanceof AnnotationNode && astNodes[1] instanceof ClassNode) {
			localTransform(astNodes[0], astNodes[1], source)
		} else if (astNodes[0] instanceof ModuleNode && astNodes[0]?.packageNode?.name) {
			globalTransform(astNodes[0], source)
		}
	}

	@Override
	public final void visit(ASTNode[] astNodes, SourceUnit source) {
		if (astNodes == null || astNodes.length == 0) {
			return;
		}

		if (useSynchronization) {
			synchronized (this) {
				transform(astNodes, source);
			}
		} else {
			transform(astNodes, source);
		}
	}

	protected void addError(String msg, ASTNode expr, SourceUnit source) {
		int line = expr?expr.lineNumber:1;
		int col = expr?expr.columnNumber:1;
		SyntaxException se = new SyntaxException(msg + '\n', line, col)
		SyntaxErrorMessage sem = new SyntaxErrorMessage(se, source)
		source.errorCollector.addErrorAndContinue(sem)
	}
}
